import {
    InstancedMesh,
    type Material,
    Matrix4,
    Mesh,
    Vector3
} from "three";
import {PointGroup} from "./PointGroup.ts";
import {releaseMesh} from "../../../framework/util.ts";

const baseMeshGap = 0.010

export class StaticPointMesh extends PointGroup{

    meshArr?: InstancedMesh[]
    constructor(x: number, y: number) {
        super(x, y)
        this.meshArr = []
    }

    addMesh(meshList: Mesh[]) {
        // console.log('添加所有mesh, 共', meshList.length)
        let map = new Map<number, Mesh[]>()
        for (let i = 0; i < meshList.length; i++) {
            let mesh = meshList[i]
            let category = mesh.userData['category'] as number
            let arr = map.get(category)
            if (!arr) {
                arr = []
                map.set(category, arr)
            }
            arr.push(mesh)
        }

        map.forEach((arr: Mesh[]) => {
            // console.log("添加一组, 类型", key, "数量", arr.length)
            this.addGroup(arr)
        })
    }

    private addGroup(list:Mesh[]) {
        let sample = list[0]
        let mat = (sample.material as Material).clone()
        let geo = sample.geometry.clone()
        let insMesh = new InstancedMesh(geo, mat, list.length)
        // console.log("配置mesh item, 总共", list.length)
        list.forEach((mesh: Mesh, index: number) => {
            let pos = mesh.position
            let scale = mesh.scale
            this.configMesh(pos, scale, insMesh, index)
            releaseMesh(mesh)
        })
        insMesh.matrixWorldNeedsUpdate = true
        this.add(insMesh)
        this.meshArr?.push(insMesh)
    }

    private configMesh(pos: Vector3, scale: Vector3, insMesh: InstancedMesh, index: number) {
        // console.log('配置第', index, '个')
        // console.log('pos', pos.x, pos.y, baseMeshGap)
        // console.log('scale', scale.x, scale.y, scale.z)
        let matrix = new Matrix4()
        matrix.makeScale(scale.x, scale.y, scale.z)
        matrix.setPosition(pos.x, pos.y, baseMeshGap)
        insMesh.setMatrixAt(index, matrix)
    }
    disposeAll() {
        for (let mesh of this.meshArr!) {
            this.remove(mesh)
        }
        let length = this.meshArr!.length
        for (let i = 0; i < length; i++) {
            let mesh = this.meshArr!.shift()
            if (!mesh) {
                continue
            }
            let m = mesh as InstancedMesh
            releaseMesh(m)
        }
        this.meshArr = undefined
        super.dispose()
    }
}
